﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading;
using UtilZ.Dotnet.DBIBase;

namespace UtilZ.Dotnet.DBDm
{
    internal partial class DmDBAccess : DBAccessAbs
    {
        /// <summary>
        /// sql语句最大长度
        /// 65,536 * 网络数据包大小,网络数据包大小指的是用于在应用程序和关系 数据库引擎 之间进行通信的表格格式数据流(TDS) 数据包的大小。 默认的数据包大小为 4 KB，由“网络数据包大小”配置选项控制。
        /// </summary>
        private const long SQL_MAX_LENGTH = -1;
        public DmDBAccess(IDBInteraction dbInteraction, DatabaseConfig config, string databaseTypeName)
            : base(dbInteraction, config, databaseTypeName, SQL_MAX_LENGTH)
        {

        }

        /// <summary>
        /// 最优化表,回收不使用的空间,并整理数据文件的碎片
        /// </summary>
        /// <param name="tableNames">表名列表,如果为null或空,则全部执行</param>
        protected override void PrimitiveOptimizeTable(List<string> tableNames)
        {
            /********************************************************************************
             * 执行完第6步，添加数据时，依然收到“磁盘空间不足”的报错，因为这时候应用回滚段还未清理，磁盘空间并未释放。
             * 未清理原因：由于需要根据回滚记录回溯、还原物理记录的历史版本信息，而不能在事务提交时立即清除当前事务产生的回滚记录。
             * 但是，如果不及时清理回滚段，可能造成回滚段空间的不断膨胀，占用大量磁盘空间。
             * DM基于上述原因提供了自动清理、回收回滚段空间的机制。采取保留回滚段一段时间，然后自动清理回滚段空间的方式。
             * 这个保留回滚段的时间长度由UNDO_RETENTION参数指定，默认数值是900，单位是秒。
             * 这个参数是系统级动态参数，修改后即时生效，dm.ini 文件里可以查到它的值。
             * 在这里插入图片描述
             * 通过第7步，调整UNDO_RETENTION为1秒，并预留10秒给进程清理回滚段，之后将UNDO_RETENTION恢复为900秒。
             * 以上便是关于如何通过调整UNDO_RETENTION参数值，迅速解决delete数据后不能及时释放表空间的问题的方法了。
             ********************************************************************************/

            using (var con = base.CreateConnection(DBVisitType.W))
            {
                var transaction = con.DbConnection.BeginTransaction();

                var cmd1 = con.DbConnection.CreateCommand();
                cmd1.Transaction = transaction;
                cmd1.CommandText = $"alter system set 'UNDO_RETENTION'=1;";
                cmd1.ExecuteNonQuery();

                Thread.Sleep(10);

                var cmd2 = con.DbConnection.CreateCommand();
                cmd2.Transaction = transaction;
                cmd2.CommandText = $"alter system set 'UNDO_RETENTION'=90.000;";
                cmd2.ExecuteNonQuery();

                try
                {
                    transaction.Commit();
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
            }
        }

        /// <summary>
        /// 创建数据库对象
        /// </summary>
        /// <returns></returns>
        protected override IDatabase CreateDatabase()
        {
            return new DmDatabase(this);
        }
    }
}
